由於我之前待的公司接的案子大多是製作官方網站或是活動網站,想當然耳,一定會遇到製作產品介紹、得獎名單需要利用 table 來製作表格,但相信各位一定都曉得,客戶永遠不知道自己要的是什麼!畫面一定是改了又改、改了又改,雖然有像 Dreamweaver 這種軟體可以整行或是整列的修改,但是_誰會花錢去買_有時候要新 / 刪 / 修 class 還是得慢慢地複製貼上,如果你會利用 Sublime Text 2 / 3 的批次修改,或許會快一些。
但各位看倌,看到今天的標題了嗎? repeat !以後遇到這種重複的工作,交給 ng-repeat 就對了,絕對是快又有效。
當初見識到 ng-repeat 的功能時,我又嚇了一跳(我好像很容易受驚 =D )
究竟,你的資料格式,是 Array 謀害?
如果你的資料是像:
$scope.array = [90, 83, 59, 100];
非常單純的 array 型式,你只需要在 HTML 中輸入:
<table>
<tr ng-repeat="item in array">
<td ng-bind="item"></td>
</tr>
</table>
在上方的 code 當中 item in array 的 array 指的就是 controller 的 $scope.array ,而 item 指的就是 $scope.array 當中的各個元素,這種用法有點類似於 JavaScript for (index in array) {}; ,接著將各個元素利用 td 去 bind 出來。
而每取一次元素, ng 就會自行新增相關的 HTML ,如範例的中 tr 、 td ,於是結果如下:
<table>
<!-- ngRepeat: item in array -->
<tr ng-repeat="item in array" class="ng-scope">
<td ng-bind="item" class="ng-binding">90</td>
</tr>
<tr ng-repeat="item in array" class="ng-scope">
<td ng-bind="item" class="ng-binding">83</td>
</tr>
<tr ng-repeat="item in array" class="ng-scope">
<td ng-bind="item" class="ng-binding">59</td>
</tr>
<tr ng-repeat="item in array" class="ng-scope">
<td ng-bind="item" class="ng-binding">100</td>
</tr>
</table>
是不是很快速地就完成了一張表格!
還是 Object 糾葛?
但如果你今天的資料格式是像這種:
$scope.object = {
'王大明': 90,
'王二明': 83,
'王三明': 59,
'王小明': 100
};
如果是單純的只想把值列出來,那只需要這樣寫:
<tr ng-repeat="item in object">
<td ng-bind="item"></td>
</tr>
可是,如果沒有把 name 列出來,我不曉得這是誰的分數啊!這表示需要兩個參數才能做到同時列出 name, value ,所以必須將 HTML 改寫如下:
<tr ng-repeat="(key, value) in object">
<td><span ng-bind="key"></span>: <span ng-bind="value"></span></td>
</tr>
亦或是背後又有隱藏不可告人的 JSON 呢?
在 Day 03 - 3 中,可以發現資料的排列順序,並不是依照_王大明_、王二明、王三明、王小明,而是利用 Array.sort() 的方式去做排列,但...我就是想要依照順序排列啊!
在此我的作法是再包一層 Array 。
我將資料格式改寫如下:
$scope.data = [{
'王大明': 90
}, {
'王二明': 83
}, {
'王三明': 59
}, {
'王小明': 100
}];
而在 HTML 的部分,改為:
<tr ng-repeat="obj in data">
<td ng-repeat="(key, value) in obj">
<span ng-bind="key"></span>:
<span ng-bind="value"></span>
</td>
</tr>
可以看到是利用雙層 ng-repeat 的方式去做,第一層的 ng-repeat 負責拆解 Array ,第二層的 ng-repeat 負責拆解 Object ,如此,便可依照順序,且同時取得 name 及 value 。
讓我們繼續看下去(背景 Fade Out)
在 ng 的官網 API 文件中,可以看到 ng-repeat 提供了特殊的屬性讓我們應用,分別為 $index, $first, $middle, $last, $even, $odd 。
那...就直接給它用下去啦!
HTML 改寫為:
<tr ng-repeat="obj in data">
<td>學號:
<span ng-bind="$index"></span>
</td>
<td ng-repeat="(key, value) in obj">
<span ng-bind="key"></span>:
<span ng-bind="value"></span>
</td>
<td>學號是奇數?
<span ng-bind="$odd"></span>
</td>
<td>學號是偶數?
<span ng-bind="$even"></span>
</td>
<td>排行是老大?
<span ng-bind="$first"></span>
</td>
<td>排行最小?
<span ng-bind="$last"></span>
</td>
<td>排行中間?
<span ng-bind="$middle"></span>
</td>
</tr>
我想,看輸出結果就相當明瞭各屬性所代表的意義了吧 =D 。
在此就不多再多贅言。
(樣式有套過 Twitter Bootstrap 所以變漂亮 :P )
解析
*****在使用 ng-repeat 的時候,請先思考一下!想要怎樣的輸出方式?針對輸出的方式,再來整理資料結構。
*****善用 ng 所提供的特殊屬性,在往後的專案裡,處理資料將會更得心應手。(尤其是 $index =D )
野生 ng-repeat
一般而言,會將所展示的列表 / 清單資料以 table Tag 的方式呈現,在 tr Tag 中使用 ng-repeat ,接著再於 td Tag 中,以想要的方式呈現資料。
但在 ng 官網中可以看見,可以以另一種方式來呈現重複性的資料。此種方式不再侷限於 table 的使用,而是以一組 HTML 的方式 repeat 。
HTML code 如下:
<header ng-repeat-start="item in data">
學號:
<span ng-bind="$index"></span>
</header>
<div class="body">
姓名:
<span ng-repeat="(key, value) in item" ng-bind="key"></span>
</div>
<footer>
分數:
<span ng-repeat="value in item" ng-bind="value"></span>
</footer>
<hr ng-repeat-end>
*****可由範例中看出,資料已不再侷限使用 table 排版,而可以更隨心所欲的添加 HTML code 來優化視覺以及資料的結構性。
而使用的方式即是在 template 的起始 Tag 使用 ng-repeat-start ,template 的結尾 Tag 使用 ng-repeat-end 即可。
*****此外,如果 repeat 的資料無須複雜的 HTML 來排版,也可在自身 repeat 的同時,綁定資料。
如同範例中:
<span ng-repeat="(key, value) in item" ng-bind="key"></span>
<span ng-repeat="value in item" ng-bind="value"></span>
此文同步更新於 EdenYeh's GitHub
歡迎各位多給我些指教,我會虛心學習的 =D